package com.zwh.se.collection.concurrent.blocking_queue;

import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;

/**
 * @author yexi
 * SynchronousQueue:一个阻塞队列,且每次的插入操作都必须等待另一个线程的对应删除操作,反之亦然。
 * 同步队列没有任何内部容量,一个容量也没有。
 * 你无法peek同步队列,因为一个元素仅在您尝试删除它时才存在;除非另一个线程试图删除它,否则您不能插入元素(无论使用任何方法);你不能迭代，因为没有什么可以迭代的。
 * 简单来说,这相当于是一个空队列,一个更好的理解不如说它像是一个传送门。
 * <p>
 * 这个特殊的队列设计的意义：提供方便高效的线程之间的数据传送,且效率极高,不会产生队列中数据争抢的问题。队列就相当于是一个标记。
 * 举例：t2线程放入数据,t1线程同时来取数据(如果没有数据则堵塞),但是数据并没有置入队列就直接被t1给取走了。
 */
@SuppressWarnings({"rawtypes", "unchecked"})
public class SynchronousQueueDemo {
    public static void main(String[] args) throws InterruptedException {
        SynchronousQueue synchronousQueue = new SynchronousQueue();
        try {
            synchronousQueue.add("aaa");
        } catch (Exception e) {
            //没有容量的概念,所以会直接报错队列已满
            System.out.println("\033[31;4m" + e + "\033[0m");
        }

        //创建一个取数据线程
        new Thread(() -> {
            int count = 0;
            while (true) {
                try {
                    if (count < 3) {
                        // 不要使用peek(),因为该方法只会检索而不会将元素从队列中拿走(因此synchronousQueue对该方法的实现直接简单粗暴地返回了null)
//                        System.out.println(synchronousQueue.peek());
                        //take()方法取不出元素就会发生堵塞,但是如果需要有超时检测的机制的话就不能用它了
                        System.out.println(synchronousQueue.take());
                    } else {
                        //设置一个阻塞事件：超出事件就不阻塞了
                        // poll()——在等待时间之内检索并删除此队列的头部。如果超过了指定的等待时间，则返回null。
                        Object result = synchronousQueue.poll(4, TimeUnit.SECONDS);
                        System.out.println(result);
                        if (result == null) {
                            break;
                        }
                    }
                    count++;
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();

        //再创建一个放数据线程
        new Thread(() -> {
            try {
                //由于队列没有容量,所以放入元素一定会堵塞
                synchronousQueue.put("aaa");
                synchronousQueue.put("bbb");
                synchronousQueue.put("ccc");
                synchronousQueue.put("ddd");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();


    }
}
